package com.longyou.comm.conntroller;

import static org.cloud.constant.CoreConstant.LOGIN_LOCKER_IP_REF_KEY;
import static org.cloud.constant.CoreConstant.TEL_VALIDATE_CODE_ERROR;
import static org.cloud.constant.CoreConstant.USER_LOCK_IP_MAP;
import static org.cloud.constant.LoginTypeConstant.LoginTypeEnum.LOGIN_BY_ADMIN_USER;

import com.longyou.comm.service.FrameUserRefService;
import com.unkow.first.telegram.constant.TelConstant.TelMessageOperate;
import com.unkow.first.telegram.dto.TelValidateCodeCheckDTO;
import com.unkow.first.telegram.util.TelValidateCodeUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.cloud.constant.CoreConstant.AuthMethod;
import org.cloud.constant.CoreConstant.OperateLogType;
import org.cloud.context.RequestContextManager;
import org.cloud.core.redis.RedisUtil;
import org.cloud.dimension.annotation.SystemResource;
import org.cloud.entity.LoginUserDetails;
import org.cloud.exception.BusinessException;
import org.cloud.logs.annotation.AuthLog;
import org.cloud.utils.IPUtil;
import org.cloud.vo.CommonApiResult;
import org.cloud.vo.FrameUserRefVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/app/userRef")
@Slf4j
@Api(tags = "用户关联信息相关", value = "用户关联信息相关")
public class AppUserRefController {

    @Autowired
    private FrameUserRefService frameUserRefService;
    @Value("${spring.security.ipLoginLockFlag:false}")
    private Boolean ipLoginLockFlag;

    @ApiOperation(value = "用户登录IP绑定是否开放")
    @SystemResource(value = "ipLoginLockFlagOpen", description = "用户登录IP绑定是否开放", authMethod = AuthMethod.NOAUTH)
    @RequestMapping(method = RequestMethod.POST, value = "/ipLoginLockFlagOpen")
    public CommonApiResult<Boolean> ipLoginLockFlagOpen() throws BusinessException {
        return CommonApiResult.createSuccessResult(ipLoginLockFlag);
    }

    @ApiOperation(value = "校验用户是否绑定登录IP")
    @SystemResource(value = "isBindLoginIp", description = "校验用户是否绑定登录IP", authMethod = AuthMethod.ALLSYSTEMUSER)
    @RequestMapping(method = RequestMethod.POST, value = "/isBindLoginIp")
    public CommonApiResult<Boolean> isBindLoginIp(HttpServletRequest request) throws BusinessException {
        LoginUserDetails loginUser = RequestContextManager.single().getRequestContext().getUser();
        return CommonApiResult.createSuccessResult(isIpLoginLockBind(loginUser, request));
    }

    /**
     * 修改IP地址登录的限制
     *
     * @return
     * @throws BusinessException
     */
    @ApiOperation(value = "修改IP地址登录的限制")
    @AuthLog(bizType = "framework", desc = "用户更改IP地址登录限制", operateLogType = OperateLogType.LOG_TYPE_BACKEND)
    @SystemResource(value = "addUserRef", description = "更改或者增加登录绑定的IP地址", authMethod = AuthMethod.ALLSYSTEMUSER)
    @RequestMapping(method = RequestMethod.POST, value = "/changeLoginIp")
    public CommonApiResult<String> addUserRef(@RequestBody TelValidateCodeCheckDTO checkDTO, HttpServletRequest request) throws BusinessException {
        String newIp = IPUtil.single().getIpAddress(request);
        checkDTO.setOperate(TelMessageOperate.MODIFY_LOGIN_LOCKER_IP);
        Assert.isTrue(TelValidateCodeUtil.single().checkValidateCode(checkDTO), TEL_VALIDATE_CODE_ERROR);
        LoginUserDetails loginUser = RequestContextManager.single().getRequestContext().getUser();
        FrameUserRefVO vo = frameUserRefService.getUserRefByAttributeName(loginUser.getId(), LOGIN_LOCKER_IP_REF_KEY);
        if (vo == null) {
            FrameUserRefVO createVo = FrameUserRefVO.builder()
                                                    .createBy(loginUser.getUsername())
                                                    .updateBy(loginUser.getUsername())
                                                    .updateDate(new Date())
                                                    .createDate(new Date())
                                                    .attributeName(LOGIN_LOCKER_IP_REF_KEY)
                                                    .attributeValue(newIp)
                                                    .userId(loginUser.getId())
                                                    .build();
            frameUserRefService.create(createVo);
        } else {
            vo.setAttributeValue(newIp);
            vo.setUpdateBy(loginUser.getUsername());
            vo.setUserId(loginUser.getId());
            vo.setUpdateDate(new Date());
            frameUserRefService.update(vo);
        }
        RedisUtil.single().hashSet(USER_LOCK_IP_MAP, loginUser.getId().toString(), newIp);
        // 剔除其它用户
        RedisUtil.single().removeUserLoginToken(loginUser.getId());
        return CommonApiResult.createSuccessResult(newIp);
    }


    private Boolean isIpLoginLockBind(LoginUserDetails user, HttpServletRequest request) {
        if (ipLoginLockFlag && LOGIN_BY_ADMIN_USER.userType.equals(user.getUserType())) {
            return IPUtil.single().getIpAddress(request).equalsIgnoreCase(RedisUtil.single().hashGet(USER_LOCK_IP_MAP, user.getId().toString()));
        }
        return false;
    }

    @ApiOperation(value = "获取当前请求的IP")
    @SystemResource(authMethod = AuthMethod.NOAUTH)
    @RequestMapping(method = RequestMethod.POST, value = "/getCurrentIp")
    public CommonApiResult<String> getCurrentIp(HttpServletRequest request) throws BusinessException {
        return CommonApiResult.createSuccessResult(IPUtil.single().getIpAddress(request));
    }
}
